package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ProductApiService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class ProductApiServiceImpl implements ProductApiService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate redisTemplate;

    //1、根据三级分类ID 查询一二三级分类
    @Override
    @GmallCache(prefix = "getBaseCategoryView")
    public BaseCategoryView getBaseCategoryView(Long category3Id) {
        return baseCategoryViewMapper.selectById(category3Id);
    }

    //2、查询Sku中的信息  sku_info  查询Sku中的图片  sku_image
    @Override
    @GmallCache(prefix = "getSkuInfo")
    public SkuInfo getSkuInfo(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        List<SkuImage> skuImageList = skuImageMapper.selectList(new QueryWrapper<SkuImage>()
                .eq("sku_id", skuId));
        skuInfo.setSkuImageList(skuImageList);
        return skuInfo;

/* *************Redisson设置缓存
        //设置key值
        String cacheKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
        //根据key值取缓存中的v，未进库中查找，当前null
        SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
        if (skuInfo != null) {//缓存已含数据
            return skuInfo;
        } else {//缓存中没有数据
            //锁的key值，根据当前k上锁解锁
            String cacheLockKey = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKULOCK_SUFFIX;
            RLock lock = redissonClient.getLock(cacheLockKey);//生成该k名的锁
            try {
                //上锁    过期不候锁-->不进true条件
                //        不见不散-->等待结束进true
                boolean tryLock = lock.tryLock(1, 2, TimeUnit.SECONDS);//（过期不候的等待时间，锁上的持续时间，单位）
                //1、库内查找
                if (tryLock) {
                    skuInfo = skuInfoMapper.selectById(skuId);
                    if (skuInfo != null) {//① 库内有数据
                        List<SkuImage> skuImageList = skuImageMapper.selectList(new QueryWrapper<SkuImage>()
                                .eq("sku_id", skuId));
                        skuInfo.setSkuImageList(skuImageList);
                        //查找的数据放入缓存（k，v，缓存保存时间，随机增加保存时间，时间单位）
                        redisTemplate.opsForValue().set(cacheKey, skuInfo, RedisConst.SKUKEY_TIMEOUT + new Random().nextInt(300), TimeUnit.SECONDS);
                    } else {//② 库内无数据，返回空值放进缓存
                        skuInfo = new SkuInfo();
                        redisTemplate.opsForValue().set(cacheKey, skuInfo, 5, TimeUnit.MINUTES);
                    }
                }
                //2、过期不候未取到锁进缓存查找
                else {
                    TimeUnit.SECONDS.sleep(2);//预防锁内数据未执行完
                    return (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {//解锁
                lock.unlock();
            }
        }
        return skuInfo;
*/
    }

    //3、查询价格
    @Override
    @GmallCache(prefix = "getPrice")
    public BigDecimal getPrice(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if (skuInfo != null) {
            return skuInfo.getPrice();
        }
        return null;
    }

    //4、查询spu中总销售属性 及属性值   同时选中一个默认商品 ( SQL相当难度 ）
    @Override
    @GmallCache(prefix = "getSaleAttrAndValeAndChecked")
    public List<SpuSaleAttr> getSaleAttrAndValeAndChecked(Long skuId, Long spuId) {
        return spuSaleAttrMapper.getSaleAttrAndValeAndChecked(skuId, spuId);
    }

    //5、查询页面上 组合与skuId之间关系  { 1|5|7 ：skuId,1|4|7 : skuId } json格式的字符串
    @Override
    @GmallCache(prefix = "getSkuValueIdsMap")
    public Map<String, String> getSkuValueIdsMap(Long spuId) {
        List<Map<String, String>> skuValueIdsMapList = skuSaleAttrValueMapper.getSkuValueIdsMap(spuId);
        Map<String, String> result = new HashMap<>();
        skuValueIdsMapList.forEach(skuValueIdsMap -> {
            result.put(String.valueOf(skuValueIdsMap.get("value_ids")), String.valueOf(skuValueIdsMap.get("sku_id")));
        });
        return result;
    }

    @Override
    public List<BaseCategoryView> getBaseCategoryViewAll() {
        return baseCategoryViewMapper.selectList(null);
    }

    @Override
    public BaseTrademark getBaseTrademark(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }

    @Override
    public List<SkuAttrValue> getSkuAttrValue(Long skuId) {
        return skuAttrValueMapper.getSkuAttrValue(skuId);
    }

    @Resource
    private SkuAttrValueMapper skuAttrValueMapper;
    @Resource
    private BaseTrademarkMapper baseTrademarkMapper;
    @Resource
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    @Resource
    private SpuSaleAttrMapper spuSaleAttrMapper;
    @Resource
    private SkuImageMapper skuImageMapper;
    @Resource
    private SkuInfoMapper skuInfoMapper;
    @Resource
    private BaseCategoryViewMapper baseCategoryViewMapper;
}
